package lpg;

class IntArrayList
{
    IntArrayList(int initialCapacity)
    {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
        elementData = new int[initialCapacity];
    }

    IntArrayList()
    {
        this(0);
    }

    private void ensureCapacity(int minCapacity)
    {
        int oldCapacity = elementData.length;
        if (minCapacity > oldCapacity)
        {
            int[] oldData = elementData;
            int newCapacity = (oldCapacity * 3) / 2 + 1;
            if (newCapacity < minCapacity)
                newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
            elementData = new int[newCapacity];
            if (size > 0)
                System.arraycopy(oldData, 0, elementData, 0, size);
        }
    }

    int size()
    {
        return size;
    }

    boolean isEmpty()
    {
        return size == 0;
    }

    int get(int index)
    {
        rangeCheck(index);
        return elementData[index];
    }

    boolean contains(int element)
    {
        for (int i = 0; i < size; i++)
            if (elementData[i] == element)
                return true;
        return false;
    }

    int set(int index, int element)
    {
        rangeCheck(index);

        int oldValue = elementData[index];
        elementData[index] = element;
        return oldValue;
    }

    void add(int e)
    {
        ensureCapacity(size + 1);
        elementData[size++] = e;
    }

    void add(int index, int element)
    {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);

        ensureCapacity(size + 1);
        if (size > index)
            System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;
        size++;
    }

    int remove(int index)
    {
        rangeCheck(index);

        int oldValue = elementData[index];

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        size--;

        return oldValue;
    }

    void clear()
    {
        size = 0;
    }

    void addAll(IntArrayList c)
    {
        if (c.size > 0)
        {
            int newSize = size + c.size;
            ensureCapacity(newSize);
            System.arraycopy(c.elementData, 0, elementData, size, c.size);
            size = newSize;
        }
    }

    void removeRange(int fromIndex, int toIndex)
    {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("Index:" + fromIndex);
        if (toIndex > size)
            toIndex = size;
        if (fromIndex > toIndex)
            throw new IndexOutOfBoundsException();
        int len = toIndex - fromIndex;
        if (len > 0)
        {
            int numMoved = size - toIndex;
            if (numMoved > 0)
                System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);
            size -= len;
        }
    }

    public String toString()
    {
        int max = size - 1;
        if (max < 0)
            return "[]";

        StringBuilder buffer = new StringBuilder();
        buffer.append('[');
        for (int i = 0; ; i++)
        {
            buffer.append(elementData[i]);
            if (i == max)
                return buffer.append(']').toString();
            buffer.append(',');
        }
    }

    private void rangeCheck(int index)
    {
        if (index >= size)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
    }

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer.
     */
    private int[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     */
    private int size = 0;

}
